package se.jayway.millionaire.internal.game;

import java.util.List;

import se.jayway.millionaire.internal.config.Configuration;
import se.jayway.millionaire.model.game.Answer;
import se.jayway.millionaire.model.game.GameRound;
import se.jayway.millionaire.model.game.GameRoundFinishedException;
import se.jayway.millionaire.model.game.GameSession;
import se.jayway.millionaire.model.game.PlayerChoice;
import se.jayway.millionaire.model.game.Question;
import se.jayway.millionaire.model.repository.Solution;

public class SimpleGameRound implements GameRound {

	private final Solution solution;
	private SimplePlayerChoice[] playerChoices;
	private boolean isFinished;
	private int noAnswerCount;
	private int correctAnswerCount;
	private int wrongAnswerCount;
	
	public SimpleGameRound(Solution solution, List<GameSession> gameSessions) {
		this.solution = solution;
		createPlayerChoices(gameSessions);
	}
	
	private void createPlayerChoices(List<GameSession> gameSessions) {
		int sessionCount = gameSessions.size();
		playerChoices = new SimplePlayerChoice[sessionCount];
		for (int i = 0; i < sessionCount; i++) {
			playerChoices[i] = new SimplePlayerChoice(this, gameSessions.get(i));
		}
	}

	public void waitUntilFinished() {
		checkIfFinished();
		try {
			Thread.sleep(Configuration.GAME_ROUND_TIME_OUT);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		isFinished = true;
	}

	private void checkIfFinished() {
		if (isFinished()) {
			throw new GameRoundFinishedException("Sorry, this game round is finished");
		}
	}

	protected void notifyNewGameRound() {
		for (PlayerChoice playerChoice : playerChoices) {
			GameSession gameSession = playerChoice.getGameSession();
			gameSession.getPlayer().onNewGameRound(playerChoice);
		}
	}

	protected void notifyGameRoundFinished() {
		for (PlayerChoice playerChoice : playerChoices) {
			GameSession gameSession = playerChoice.getGameSession();
			gameSession.getPlayer().onFinishedGameRound(playerChoice, solution.getCorrectAnswer());
		}
	}

	// @OnceAndOnlyOnce
	public void updateScoreCard() {
		for (PlayerChoice playerChoice : playerChoices) {
			// TODO Remove dependency to implementation
			SimpleGameSession gameSession = (SimpleGameSession) playerChoice.getGameSession();
			gameSession.updateScoreCard(playerChoice, solution.getCorrectAnswer());
			
			Answer playerAnswer = playerChoice.getPlayerAnswer();
			if (playerAnswer == null) {
				noAnswerCount++;
			} else if (playerAnswer.equals(solution.getCorrectAnswer())) {
				correctAnswerCount++;
			} else {
				wrongAnswerCount++;
			}
		}
	}

	
	protected void notifyWinners() {
		for (PlayerChoice playerChoice : playerChoices) {
			GameSession gameSession = playerChoice.getGameSession();
			if (playerChoice.getGameSession().countCorrectAnswersInRow() == Configuration.NUMBER_OF_CORRECT_ANSWERS_IN_A_ROW_TO_WIN) {
				gameSession.getPlayer().onWin(playerChoice);
			}
		}
	}
	
	public int countCorrectAnswers() {
		return correctAnswerCount;
	}

	public int countWrongAnswers() {
		return wrongAnswerCount;
	}
	
	public int countNoAnswers() {
		return noAnswerCount;
	}

	public int countPlayers() {
		return playerChoices.length;
	}

	public boolean isFinished() {
		return isFinished;
	}

	public Question getQuestion() {
		return solution.getQuestion();
	}
}
